package org.example.springweibo.exception;


import lombok.extern.slf4j.Slf4j;
import org.example.springweibo.jsonresult.JsonResult;
import org.example.springweibo.serviceode.ServiceCode;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

/**
 * ControllerAdvice注解: 标识当前的类为全局异常处理器类型;可以处理由控制器抛出的异常
 *   1.如果Controller中抛出了异常,首先看是否定义了全局异常处理器;
 *   2.如果定义了会在全局异常处理器中找对应的异常处理方法;
 *   3.如果找到了对应的异常处理方法,则执行异常处理方法中的代码逻辑.
 *
 * RestControllerAdvice注解: 复合注解,相当于 @ResponseBody + @ControllerAdvise注解
 */
//@ControllerAdvice
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {/*全局异常处理器*/
    @ExceptionHandler
    public JsonResult handleServiceException(ServiceException e){
        return JsonResult.fail(e);
    }

    @ExceptionHandler
    public JsonResult handleBindExceptin(BindException e){
        String message=e.getFieldError().getDefaultMessage();
        return JsonResult.fail(ServiceCode.ERROR_BAD_REQUEST,message);
    }

    @ExceptionHandler
    public JsonResult handleConstrainViolationException(ConstraintViolationException e){
        /*
         * ConstraintViolationException是一个java中的异常类，通常与数据访问和持久化框架一起使用
         * 当使用这些框架进行数据操作时，如果违反了定义的约束条件，就会排除ContrainViolationException
         * 这种异常表示在执行数据库操作期间发生了约束违规的情况
         * */
        String message=null;
        Set<ConstraintViolation<?>> constraintViolations=e.getConstraintViolations();
        /*
         * ConstraintViolation 是一个常见的概念，指在应用程序中违反了预定约束条件的情况
         * 我们经常使用约束来限制数据的有效性和一致性，在数据中，可以定义表和列级别的约束
         * 例如：唯一约束，非空约束，外键约束
         * */
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            message=constraintViolation.getMessage();/*getMessage() 本质是this.interpolatedMessage;*/
        }
        /*ERROR_BAD_REQUEST:请求参数错误*/
        return JsonResult.fail(ServiceCode.ERROR_BAD_REQUEST,message);
    }

    @ExceptionHandler
    public JsonResult handleAccessDeniedException(AccessDeniedException e){
        String message="操作失败，您当前登录的账号无此操作权限！";
        /*ERROR_FORBIDDEN:禁止访问，用于无权限*/
        return JsonResult.fail(ServiceCode.ERROR_FORBIDDEN,message);
    }

    @ExceptionHandler
    public JsonResult handleThrowable(Throwable e){
        log.warn("程序运行过程中出现未知异常：",e);
        String message="操作失败，服务器忙，请稍后再试！";
        /*ERROR_UNKNOWN:其他异常*/
        return JsonResult.fail(ServiceCode.ERROR_UNKNOWN,message);
    }
}




